//
#include "../function.h"

void initbez(bezierP*bp)//初始化链表
{
	bp->phead = NULL;
	bp->pend = NULL;
	bp->count = 0;
}
point * getp(bezierP*pot,int num)//获得点
{
	//获得点
	if(pot->count>0&&pot->count>=num)
	{
		point*p = pot->phead;
		if(num==1)
			return p;
		for(int i = 1;i<num;i++)
			p = p->next;
		return p;
	}
	return NULL;
}
void changp(bezierP*pot,int num,double x,double y)//修改点
{
  /*  point*p = pot->phead;
	if(num==1)
	{
		p->x = x;
		p->y = y;
	}
	else if(num==pot->count)
	{
		pot->pend->x = x;
		pot->pend->y = y;
	}
	else
	{
		for(int i = 1;i<num;i++)
			p = p->next;
		p->x = x;
		p->y = y;
	}*/
	point*p=getp(pot,num);
	p->x = x;
	p->y = y;
}
void addp(bezierP*po,double x,double y)//末尾添加点
{
	if(po->phead==NULL)
	{
		po->phead = (point*)malloc(sizeof(point));
		po->phead->x = x;
		po->phead->y = y;
		po->phead->next = NULL;
		po->pend = po->phead;
	}
	else{
		point*p = (point*)malloc(sizeof(point));
		p->x = x;
		p->y = y;
		p->next = NULL;
		po->pend->next = p;
		po->pend = po->pend->next;
	}
	po->count++;
}
void delendp(bezierP*po)//删除末尾点
{
	if(po->count>1)
	{
		point*p = getp(po,po->count);
		free(p);
		po->count--;
		po->pend = getp(po,po->count);
		po->pend->next = NULL;
	}
	else
	{
		if(po->phead!=NULL)
		{
			free(po->phead);
		}
		if(po->pend!=NULL)
		{
			free(po->phead);
		}
		po->phead = NULL;
		po->phead = NULL;
		po->count = 0;
	}
}
void clearbezier(bezierP*po)//清空链表
{
	while(po->phead!=po->pend)
	{
		point*p = po->phead;
		po->phead = po->phead->next;
		free(p);
	}
	free(po->phead);
	po->phead = NULL;
	po->pend = NULL;
	po->count = 0;
}
//在起点为(x1,y1)，终点为(x2,y2)的线段上移动长度为long,得到点(x,y),和所占比例k
void stepgetpbezier(double x1,double y1,double x2,double y2,double lon,double*x,double*y,double*k)
{
	*k = lon/sqrt(pow(y2-y1,2)+pow(x2-x1,2));
	if(fabs(x2-x1)<0.0001)
		*x = x1;
	else
		*x = ((x2-x1)>0?1:-1)*sqrt(pow((double)lon,2)/(pow((double)(y2-y1)/(x2-x1),2)+1))+x1;
	if(fabs(y2-y1)<0.0001)
		*y = y1;
	else
		*y = ((y2-y1)>0?1:-1)*sqrt(pow((double)lon,2)/(pow((double)(x2-x1)/(y2-y1),2)+1))+y1;
}
//在起点为(x1,y1)，终点为(x2,y2)的线段上所占比例为k,得到点(x,y)
void kgetp(double x1,double y1,double x2,double y2,double k,double*x,double*y)
{
	if(fabs(x2-x1)<0.0001)
		*x = x1;
	else
		*x = ((x2-x1)>0?1:-1)*sqrt((pow((double)k,2)*(pow((double)(y2-y1),2)+pow((double)(x2-x1),2)))/(pow((double)((x2-x1)/(y2-y1)),2)+1))+x1;
	if(fabs(y2-y1)<0.0001)
		*y = y1;
	else
		*y = ((y2-y1)>0?1:-1)*sqrt((pow((double)k,2)*(pow((double)(y2-y1),2)+pow((double)(x2-x1),2)))/(pow((double)((y2-y1)/(x2-x1)),2)+1))+y1;
}
void findp(bezierP*bp,double lon,double*x,double*y)//在bp点集中找出第一段移动距离为lon的贝塞尔点(x,y)
{
	bezierP buf;//临时点集
	initbez(&buf);
	double k;//比例
	int u = 0;
	for(int i = 1;i<=bp->count;i++)//复制所有点
	{
		point*p = getp(bp,i);
		//    if(p!=NULL)
		addp(&buf,p->x,p->y);
	}
	while(buf.count>1)
	{
		for(int i = 1;i<=bp->count;i++)//操作所有点
		{
			point*p = getp(&buf,i);
			point*q = getp(&buf,i+1);
			double x1,y1;
			if(p!=NULL&&q!=NULL)
			{
				if(i==1&&u==0)
				{
					stepgetpbezier(p->x,p->y,q->x,q->y,lon,&x1,&y1,&k);//
					u = 1;
				}
				else
					kgetp(p->x,p->y,q->x,q->y,k,&x1,&y1);
				changp(&buf,i,x1,y1);
			}
		}
		delendp(&buf);
	}
	*x = getp(&buf,1)->x;
	*y = getp(&buf,1)->y;
	clearbezier(&buf);
}
int findjinpbezier(bezierP*bp,float x,float y)//找到与点(x,y)最近的点节点
{
	//  double x=(double)x1;
	//  double y=(double)y1;
	point*p = bp->phead;
	int n,n1;
	double lon;
	while(p!=bp->pend)
	{
		if(p==bp->phead)
		{
			lon = sqrt(pow((y-p->y),2)+pow((x-p->x),2));
			n = 1;
			n1 = 1;
			p = p->next;
			n1++;
		}
		else
		{
			if(lon>sqrt(pow((y-p->y),2)+pow((x-p->x),2)))
			{
				lon = sqrt(pow((y-p->y),2)+pow((x-p->x),2));
				n = n1;
			}
			n1++;
			p = p->next;
			if(p==bp->pend)
			{
				if(lon>sqrt(pow((y-p->y),2)+pow((x-p->x),2)))
				{
					lon = sqrt(pow((y-p->y),2)+pow((x-p->x),2));
					n = n1;
				}
			}
		}
	}
	return n;
}
bezierP bepo;//所有点
bezierP bebuf;//中介点
int SCRW = 1000;
int SCRH = 1200;


void bezierCreate()//界面启动时调用
{
	initbez(&bepo);
	// initbez(&bebuf);
	addp(&bepo,10,10);//添加第一个点
	srand(time(NULL));
	for(int i = 1;i<BEZIERJ -1;i++)
	{
		addp(&bepo,rand()%(SCRW-20)+10,rand()%(SCRH-20)+10);
	}
	addp(&bepo,SCRW-10,SCRH-10);//添加最后一个点 
		
}
void bezierTouchEvent(int action,float x,float y,int index,int count,float pointersX[],float pointersY[],int pointersId[])//触屏事件
{
	 //  if(action==ACTION_DOWN)
	{
		//  addp(&bepo,x,y);//添加第一个点
		float x1 = x,y1 = y;
		point*p;
		int n = findjinpbezier(&bepo,x,y);
		if(action==ACTION_MOVE)
		{
			//  addp(&bepo,x,y);//添加第一个点    
			changp(&bepo,n,x,y);//修改点     
			
			postInvalidate();//通知系统重新绘图 
		}
	}
}
void bezierDraw(int left,int top,int right,int bottom,Canvas canvas)//画图		
{
	Canvas_drawColor(canvas,RGB(255,255,255));
	Paint paint = newPaint();//创建画笔
	Paint_setTextSize(paint,32);//设置文字大小
	Canvas_drawText(canvas,"破竹 QQ:1249223183",100,100,paint);//绘制文本
	
	/*   clear(&bepo);
	addp(&bepo,10,10);//添加第一个点
	srand(time(NULL));
	for(int i = 1;i<J-1;i++)
	{
		addp(&bepo,rand()%(SCRW-20)+10,rand()%(SCRH-20)+10);
	}
	addp(&bepo,SCRW-10,SCRH-10);//添加最后一个点 
*/
	for(point*p = bepo.phead;p!=bepo.pend;p = p->next)
	{
		Canvas_drawCircle(canvas,p->x,p->y,8,paint);
		Canvas_drawLine(canvas,p->x,p->y,p->next->x,p->next->y,paint);
	}
	Canvas_drawCircle(canvas,bepo.pend->x,bepo.pend->y,8,paint);
	
	double step = 1;
	double x,y;
	point*p1 = getp(&bepo,1);
	point*p2 = getp(&bepo,2);
	double fistlong = sqrt(pow((double)(p2->y-p1->y),2)+pow((double)(p2->x-p1->x),2));
	for(double s = step;fistlong-s>0;s+=step)
	{
		findp(&bepo,s,&x,&y);//在bp点集中找出第一段移动距离为lon的贝塞尔点(x,y)
		Canvas_drawCircle(canvas,x,y,3,paint);
	}
	
	deletePaint(paint);//释放画笔
}
void bezierLoopCall()//每1毫秒就会调用这个方法1次
{
	postInvalidate();//通知系统重新绘图
	
}
void bezierSizeChange(int w,int h,int oldw,int oldh,float density)//屏幕大小发生变化时被调用 ，程序在启动后会调用一次
{
	SCRW = getScreenWidth();
	//屏幕高度
	SCRH = getScreenHeight();
}
int bezierBackPressed()//返回键按下被调用
{
	bezierDestroy();
	funnumber = 0;
	functiononCreate(funnumber);//在界面启动时调用	
	prefunnumber = funnumber;
	postInvalidate();//通知系统重新绘图
	return 0;
}
void bezierDestroy()//界面销毁被调用
{
	clearbezier(&bepo);
}